@@ -0,0 +1,30 @@ |
||
1 |
+.agent-diagram { |
|
2 |
+ position: relative; |
|
3 |
+ z-index: auto; |
|
4 |
+ |
|
5 |
+ svg.diagram { |
|
6 |
+ position: absolute; |
|
7 |
+ z-index: 1; |
|
8 |
+ } |
|
9 |
+ |
|
10 |
+ .overlay-container { |
|
11 |
+ position: absolute; |
|
12 |
+ top: 0; |
|
13 |
+ left: 0; |
|
14 |
+ z-index: auto; |
|
15 |
+ |
|
16 |
+ .overlay { |
|
17 |
+ position: relative; |
|
18 |
+ z-index: auto; |
|
19 |
+ width: 100%; |
|
20 |
+ height: 100%; |
|
21 |
+ |
|
22 |
+ .badge { |
|
23 |
+ position: absolute; |
|
24 |
+ display: none; |
|
25 |
+ color: white !important; |
|
26 |
+ z-index: 2; |
|
27 |
+ } |
|
28 |
+ } |
|
29 |
+ } |
|
30 |
+} |
@@ -6,7 +6,7 @@ module DotHelper |
||
6 | 6 |
dot.close_write |
7 | 7 |
dot.read |
8 | 8 |
} rescue false) |
9 |
- svg.html_safe |
|
9 |
+ decorate_svg(svg, agents).html_safe |
|
10 | 10 |
else |
11 | 11 |
tag('img', src: URI('https://chart.googleapis.com/chart').tap { |uri| |
12 | 12 |
uri.query = URI.encode_www_form(cht: 'gv', chl: agents_dot(agents)) |
@@ -161,4 +161,85 @@ module DotHelper |
||
161 | 161 |
} |
162 | 162 |
} |
163 | 163 |
end |
164 |
+ |
|
165 |
+ def decorate_svg(xml, agents) |
|
166 |
+ svg = Nokogiri::XML(xml).at('svg') |
|
167 |
+ |
|
168 |
+ Nokogiri::HTML::Document.new.tap { |doc| |
|
169 |
+ doc << root = Nokogiri::XML::Node.new('div', doc) { |div| |
|
170 |
+ div['class'] = 'agent-diagram' |
|
171 |
+ } |
|
172 |
+ |
|
173 |
+ svg['class'] = 'diagram' |
|
174 |
+ |
|
175 |
+ root << svg |
|
176 |
+ root << overlay_container = Nokogiri::XML::Node.new('div', doc) { |div| |
|
177 |
+ div['class'] = 'overlay-container' |
|
178 |
+ div['style'] = "width: #{svg['width']}; height: #{svg['height']}" |
|
179 |
+ } |
|
180 |
+ overlay_container << overlay = Nokogiri::XML::Node.new('div', doc) { |div| |
|
181 |
+ div['class'] = 'overlay' |
|
182 |
+ } |
|
183 |
+ |
|
184 |
+ svg.xpath('//xmlns:g[@class="node"]', svg.namespaces).each { |node| |
|
185 |
+ agent_id = (node.xpath('./xmlns:title/text()', svg.namespaces).to_s[/\d+/] or next).to_i |
|
186 |
+ agent = agents.find { |a| a.id == agent_id } |
|
187 |
+ |
|
188 |
+ count = agent.events_count |
|
189 |
+ next unless count && count > 0 |
|
190 |
+ |
|
191 |
+ overlay << Nokogiri::XML::Node.new('a', doc) { |badge| |
|
192 |
+ badge['id'] = id = 'b%d' % agent_id |
|
193 |
+ badge['class'] = 'badge' |
|
194 |
+ badge['href'] = events_path(agent: agent) |
|
195 |
+ badge['target'] = '_blank' |
|
196 |
+ badge.content = count.to_s |
|
197 |
+ |
|
198 |
+ node['data-badge-id'] = id |
|
199 |
+ |
|
200 |
+ badge << Nokogiri::XML::Node.new('span', doc) { |label| |
|
201 |
+ # a dummy label only to obtain the background color |
|
202 |
+ label['class'] = [ |
|
203 |
+ 'label', |
|
204 |
+ if agent.disabled? |
|
205 |
+ 'label-warning' |
|
206 |
+ elsif agent.working? |
|
207 |
+ 'label-success' |
|
208 |
+ else |
|
209 |
+ 'label-danger' |
|
210 |
+ end |
|
211 |
+ ].join(' ') |
|
212 |
+ label['style'] = 'display: none'; |
|
213 |
+ } |
|
214 |
+ } |
|
215 |
+ } |
|
216 |
+ |
|
217 |
+ root << Nokogiri::XML::Node.new('script', doc) { |script| |
|
218 |
+ script.content = <<-SCRIPT |
|
219 |
+$(function () { |
|
220 |
+ var svg = document.querySelector('.agent-diagram svg.diagram'); |
|
221 |
+ var overlay = document.querySelector('.agent-diagram .overlay'); |
|
222 |
+ var getTopLeft = function (node) { |
|
223 |
+ var bbox = node.getBBox(); |
|
224 |
+ var point = svg.createSVGPoint(); |
|
225 |
+ point.x = bbox.x + bbox.width; |
|
226 |
+ point.y = bbox.y; |
|
227 |
+ return point.matrixTransform(node.getCTM()); |
|
228 |
+ }; |
|
229 |
+ $(svg).find('g.node[data-badge-id]').each(function () { |
|
230 |
+ var tl = getTopLeft(this) |
|
231 |
+ $('#' + this.getAttribute('data-badge-id'), overlay).each(function () { |
|
232 |
+ var badge = $(this); |
|
233 |
+ badge.css({ |
|
234 |
+ left: tl.x - badge.outerWidth() * (2/3), |
|
235 |
+ top: tl.y - badge.outerHeight() * (1/3), |
|
236 |
+ 'background-color': badge.find('.label').css('background-color') |
|
237 |
+ }).show(); |
|
238 |
+ }); |
|
239 |
+ }); |
|
240 |
+}) |
|
241 |
+ SCRIPT |
|
242 |
+ } |
|
243 |
+ }.at('div.agent-diagram').to_s |
|
244 |
+ end |
|
164 | 245 |
end |